package com.run.runbbs.service.impl;

import com.alibaba.fastjson.JSON;
import com.run.runbbs.dao.elasticSearch.PostRepository;
import com.run.runbbs.entity.Post;
import org.elasticsearch.action.delete.DeleteRequest;
import org.elasticsearch.action.index.IndexRequest;
import org.elasticsearch.action.index.IndexResponse;
import org.elasticsearch.action.search.SearchRequest;
import org.elasticsearch.action.search.SearchResponse;
import org.elasticsearch.action.update.UpdateRequest;
import org.elasticsearch.action.update.UpdateResponse;
import org.elasticsearch.client.RequestOptions;
import org.elasticsearch.client.RestHighLevelClient;
import org.elasticsearch.common.text.Text;
import org.elasticsearch.common.unit.TimeValue;
import org.elasticsearch.common.xcontent.XContentType;
import org.elasticsearch.index.query.MultiMatchQueryBuilder;
import org.elasticsearch.index.query.QueryBuilders;
import org.elasticsearch.search.SearchHit;
import org.elasticsearch.search.builder.SearchSourceBuilder;
import org.elasticsearch.search.fetch.subphase.highlight.HighlightBuilder;
import org.elasticsearch.search.fetch.subphase.highlight.HighlightField;
import org.elasticsearch.search.sort.SortBuilders;
import org.elasticsearch.search.sort.SortOrder;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.data.domain.PageRequest;
import org.springframework.data.elasticsearch.core.query.NativeSearchQuery;
import org.springframework.data.elasticsearch.core.query.NativeSearchQueryBuilder;
import org.springframework.stereotype.Service;

import java.io.IOException;
import java.util.ArrayList;
import java.util.List;
import java.util.Map;
import java.util.concurrent.TimeUnit;
@Service
public class ElasticsearchService {

    @Autowired
    private PostRepository postRepository;
    @Autowired
    private RestHighLevelClient restHighLevelClient;

    public void savePost(Post post) throws IOException {
        IndexRequest request = new IndexRequest("runbbs_post");
        request.id(post.getId()+"").timeout(TimeValue.timeValueSeconds(1));
        request.timeout("1s");
        request.source(JSON.toJSONString(post), XContentType.JSON);
        restHighLevelClient.index(request, RequestOptions.DEFAULT);
    }

    public void updatePost(Post post) throws IOException {
        UpdateRequest request = new UpdateRequest("runbbs_post",post.getId()+"");
        request.timeout("1s");
        request.doc(JSON.toJSONString(post),XContentType.JSON);
        restHighLevelClient.update(request, RequestOptions.DEFAULT);
    }
    public void deletePost(int id) throws IOException {
        DeleteRequest request = new DeleteRequest("test", id + "");
        request.timeout("1s");
        restHighLevelClient.delete(request,RequestOptions.DEFAULT);
    }
    public List<Map<String,Object>> searchPost(String keyword, int offset, int limit) throws IOException {
//        NativeSearchQuery searchQuery=new NativeSearchQueryBuilder()
//                .withQuery(QueryBuilders.multiMatchQuery(keyword,"title","content"))
//                .withSort(SortBuilders.fieldSort("type").order(SortOrder.DESC))
//                .withSort(SortBuilders.fieldSort("score").order(SortOrder.DESC))
//                .withSort(SortBuilders.fieldSort("createTime").order(SortOrder.DESC))
//                .withPageable(PageRequest.of(0,10))
//                .withHighlightFields(
//                        new HighlightBuilder.Field("title").preTags("<em>").postTags("</em>"),
//                        new HighlightBuilder.Field("title").preTags("<em>").postTags("</em>")
//                ).build();

        SearchRequest searchRequest=new SearchRequest("runbbs_post");
        SearchSourceBuilder sourceBuilder=new SearchSourceBuilder();

        //分页
        sourceBuilder.from(offset);
        sourceBuilder.size(limit);
        //排序
        sourceBuilder.sort(SortBuilders.fieldSort("type").order(SortOrder.DESC));
        sourceBuilder.sort(SortBuilders.fieldSort("score").order(SortOrder.DESC));
        sourceBuilder.sort(SortBuilders.fieldSort("createTime").order(SortOrder.DESC));

        //匹配
        MultiMatchQueryBuilder multiMatchQueryBuilder=QueryBuilders.multiMatchQuery(keyword,"title","content");
        sourceBuilder.query(multiMatchQueryBuilder);
        sourceBuilder.timeout(new TimeValue(60, TimeUnit.SECONDS));
        //高亮
        HighlightBuilder highlightBuilder=new HighlightBuilder();
        highlightBuilder.field("title").field("content");
        highlightBuilder.preTags("<span style='color:red'>");
        highlightBuilder.postTags("</span>");
        sourceBuilder.highlighter(highlightBuilder);
        //执行
        searchRequest.source(sourceBuilder);
        SearchResponse searchResponse=restHighLevelClient.search(searchRequest, RequestOptions.DEFAULT);
        //解析结果
        ArrayList<Map<String,Object>> list=new ArrayList<>();
        for(SearchHit documentFields : searchResponse.getHits().getHits()){
            //获取高亮字段
            Map<String, HighlightField> highlightFields = documentFields.getHighlightFields();
            HighlightField title=highlightFields.get("title");
            HighlightField content=highlightFields.get("content");
            Map<String, Object> sourceAsMap = documentFields.getSourceAsMap();
            //拿到高亮字段并替换。
            if(title!=null){
                Text[] title_fragments = title.fragments();
                String n_title="";
                for(Text text : title_fragments){
                    n_title+=text;
                }
                sourceAsMap.put("title",n_title);
                //或者用这种
//                sourceAsMap.put("title",title.getFragments()[0].toString());
            }
            if(content!=null){
//                Text[] content_fragments = content.fragments();
//                String n_content="";
//                for(Text text : content_fragments){
//                    n_content+=text;
//                }
//                sourceAsMap.put("content",n_content);
                sourceAsMap.put("content",content.getFragments()[0].toString());
            }
            list.add(sourceAsMap);
        }
        return list;
    }
}
